namespace SimpleWebServices.Reflection
{
    using System.Collections.Specialized;
    using System.Net.Mail;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using Xunit;

    public sealed class ReflectionExtensionMethodsFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(typeof(ReflectionExtensionMethods).IsStatic());
        }

        [Fact]
        public void op_ToXml_objectNull()
        {
            Assert.Null((null as object).ToXml());
        }

        [Fact]
        public void op_ToXml_object_whenMailAddress()
        {
            /// MailAddress throws an InvalidOperationException if you try to do regular XML serialization

            MailAddress value = new MailAddress("john.doe@example.com", "John Doe");

            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/MailAddress[@DisplayName='John Doe'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/MailAddress[@User='john.doe'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/MailAddress[@Host='example.com'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/MailAddress[@Address='john.doe@example.com'])"));
        }

        [Fact]
        public void op_ToXml_object_whenDataCollection()
        {
            DataCollection value = new DataCollection
            {
                { "x", "1" },
                { "y", "2" },
                { "z", "3" }
            };

            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/DataCollection)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/DataCollection[@Completed='false'][@Count='3'][@Entity])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("3 = count(/DataCollection/KeyValuePair-2)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/DataCollection/KeyValuePair-2[@Key='x'][@Value='1'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/DataCollection/KeyValuePair-2[@Key='y'][@Value='2'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/DataCollection/KeyValuePair-2[@Key='z'][@Value='3'])"));
        }

        [Fact]
        public void op_ToXml_object_whenNameValueCollection()
        {
            NameValueCollection value = new NameValueCollection
            {
                { "x", "1" },
                { "y", "2" },
                { "z", "3" }
            };

            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/NameValueCollection)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/NameValueCollection[@Count='3'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("3 = count(/NameValueCollection/Value)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/NameValueCollection/Value[@Name='x'][text()='1'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/NameValueCollection/Value[@Name='y'][text()='2'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/NameValueCollection/Value[@Name='z'][text()='3'])"));
        }

        [Fact]
        public void op_ToXml_object_whenStringCollection()
        {
            StringCollection value = new StringCollection
            {
                "a", "b"
            };

            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/StringCollection)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/StringCollection[@Count='2'][@IsReadOnly='false'][@IsSynchronized='false'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/StringCollection/SyncRoot)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("2 = count(/StringCollection/String)"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/StringCollection/String[text()='a'])"));
            Assert.True((bool)value.ToXml().CreateNavigator().Evaluate("1 = count(/StringCollection/String[text()='b'])"));
        }

        [Fact]
        public void op_ToXml_object_whenString()
        {
            string expected = "<String>value</String>";
            string actual = "value".ToXml().CreateNavigator().OuterXml;

            Assert.Equal<string>(expected, actual);
        }
    }
}